package com.qd.p2p.web.action.notify;

import java.io.IOException;
import java.text.MessageFormat;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import com.google.common.base.Strings;
import com.qdlc.p2p.biz.service.TppTradeService;
import com.qdlc.p2p.biz.util.NotifyRequestHandler;
import com.qdlc.p2p.biz.web.action.BaseAction;
import com.qdlc.p2p.common.constant.Global;
import com.qdlc.p2p.common.constant.TradeStatus;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.MailUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.dto.TppTradeLog;

/**
 * 交易通知基础类
 *
 * @author wuaj
 */
public abstract class TradeNotifyBaseAction extends BaseAction {
    private Logger logger = Logger.getLogger(TradeNotifyBaseAction.class);

    @Resource
    private TppTradeService tppTradeService;

    public abstract void doAction();

    public abstract String getBusinessName();

    public abstract String getProcessName();

    /**
     * 完成状态 业务处理
     */
    public abstract void finishHandle(TradeNotifyValueEvent event);

    /**
     * 成功状态 业务处理
     */
    public abstract void successHandle(TradeNotifyValueEvent event);

    /**
     * 失败状态 业务处理
     */
    public abstract void failHandle(TradeNotifyValueEvent event);

    protected void actionHandle() {
        response.setContentType("text/html;charset=UTF-8");

        NotifyRequestHandler notifyRequest = NotifyRequestHandler.build(request);

        String tradeStatus = notifyRequest.getParam("trade_status"); // 回调状态
        String tradeNo = notifyRequest.getParam("outer_trade_no"); // 交易订单号
        String tradeAmount = notifyRequest.getParam("trade_amount"); // 投标金额

        try {
            // 只要参数中带有token参数 本地验签 否则用新浪的验签
            String url = request.getRequestURI().replaceAll(".action", "");
            String localToken = Global.getCallBackToken(url);
            boolean checkSign;
            if (StringUtil.isNotEmpty(notifyRequest.getParam("token"))) {
                checkSign = localToken.equals(notifyRequest.getParam("token"));
                logger.info(MessageFormat.format("{0} - {1}回调处理 本地 验签 状态:{2} 订单号:{3}", getBusinessName(), getProcessName(), tradeStatus, tradeNo));
            } else {
                checkSign = notifyRequest.checkSign();
                logger.info(MessageFormat.format("{0} - {1}回调处理 新浪 验签 状态:{2} 订单号:{3}}", getBusinessName(), getProcessName(), tradeStatus, tradeNo));
            }
            if (checkSign == false) {
                logger.info(MessageFormat.format("{0} - {1}回调处理失败 状态:{2} 订单号:{3} 原因:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, "验签失败"));
                print("Sign Error!");
                return;
            }

            // 交易Log
            TppTradeLog tppTradeLog = tppTradeService.find(tradeNo);
            // 订单号未生成
            if (tppTradeLog == null) {
                logger.info(MessageFormat.format("{0} - {1}回调处理失败 状态:{2} 订单号:{3} 原因:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, "该订单号不存在!"));
                print("No Exist OutTradeNo!");
                MailUtil.sendMail("系统内部Bug 需及时修复", MessageFormat.format("该订单号:{0}不存在!", tradeNo), "");
                return;
            }
            if (TradeStatus.TRADE_STATUS_INVALID.getStatus().equalsIgnoreCase(tppTradeLog.getTradeStatus())) {
                logger.info(MessageFormat.format("{0} - {1}回调无法处理 状态:{2} 订单号:{3} 原因:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, "无效订单号!"));
                print("success");
                return;
            }

            // 判断是否已经被调用过
            String status = Strings.nullToEmpty(tppTradeLog.getSinaStatus());
            // 状态是否被调用过
            logger.info(MessageFormat.format("{0} - {1}回调业务处理开始 状态:{2} 订单号:{3} 交易类型:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, tppTradeLog.getTradeType()));
            if (!status.contains(tradeStatus)) {
                // 构造事件 业务处理用
                TradeNotifyValueEvent event = new TradeNotifyValueEvent();
                event.setDepositAmount(Double.valueOf(tradeAmount));
                event.setOutOrderNo(tradeNo);
                event.setDepositStatus(tradeStatus);

                tppTradeLog.setAmount(Double.valueOf(tradeAmount)); // 交易金额
                tppTradeLog.setTradeTime(DateUtil.getNow());// 交易时间
                event.setTppTradeLog(tppTradeLog);
                if (TradeStatus.TRADE_STATUS_FINISHED.getStatus().equalsIgnoreCase(tradeStatus)) {
                    // 完成回调业务处理
                    finishHandle(event);
                } else if (TradeStatus.TRADE_STATUS_PAY_FINISHED.getStatus().equalsIgnoreCase(tradeStatus)) {
                    // 成功回调业务处理
                    successHandle(event);
                } else if (TradeStatus.TRADE_STATUS_FAILED.getStatus().equalsIgnoreCase(tradeStatus)) {
                    tppTradeLog.setAmount(0d); // 交易金额置0
                    event.setTppTradeLog(tppTradeLog);
                    // 失败回调业务处理
                    failHandle(event);
                }
            } else {
                logger.info(MessageFormat.format("{0} - {1}回调业务已被处理 状态:{2} 订单号:{3} 交易类型:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, tppTradeLog.getTradeType()));
            }
            logger.info(MessageFormat.format("{0} - {1}回调业务处理结束 状态:{2} 订单号:{3} 交易类型:{4}", getBusinessName(), getProcessName(), tradeStatus, tradeNo, tppTradeLog.getTradeType()));
            print("success");
        } catch (Exception e) {
            if (!(e instanceof BusinessException)) {
                MailUtil.sendMail("系统内部Bug 需及时修复", e);
            }
            e.printStackTrace();
            print("Service Error!");
            return;
        }
    }

    /*private QueueLog getQueueLog() {
        String orderNoStr = request.getParameter("order_no");
        long orderNo = StringUtil.isBlank(orderNoStr) ? 0l : StringUtil.toLong(orderNoStr);
        if (orderNo > 0) {
            String token = request.getParameter("token");
            if (GlobalConstant.RE_CALL_TOKEN.equalsIgnoreCase(token)) {
                throw new RedEnvelopeException("令牌不正解无法操作!", RedEnvelopeException.TYPE_JSON);
            }
            QueueLog queueLog = queueLogService.findByOrderId(orderNo);
            if (queueLog == null) {
                throw new RedEnvelopeException("该队列不存在!", RedEnvelopeException.TYPE_JSON);
            } else {
                return queueLog;
            }
        } else {
            return null;
        }
    }*/

    /**
     * 响应
     *
     * @param message 消息
     */
    private void print(String message) {
        try {
            response.getWriter().print(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
